package logicGame;

import java.awt.Color;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class Board implements Serializable {

    HashMap<Integer, Integer[]> land;
    HashMap<Integer, Integer[]> naval;
    HashMap<Integer, ArrayList<City>> city;
    HashMap<Integer, ArrayList<Army>> troop;
    HashMap<Integer, Integer[]> continent;

    public Board() {
        land = new HashMap<>();
        naval = new HashMap<>();
        city = new HashMap<>();
        troop = new HashMap<>();
        continent = new HashMap<>();
        //inicializa Arraylist Army && City em hashmaps 
        for (int i = 0; i < 23; i++) {
            troop.put(i, new ArrayList<Army>());
            city.put(i, new ArrayList<City>());
        }

        //inicializar possibiliades de mover exercitos por terra
        land.put(0, new Integer[]{1});
        land.put(1, new Integer[]{0, 2, 3, 6});
        land.put(2, new Integer[]{1, 3, 4, 5, 6, 8});
        land.put(3, new Integer[]{1, 2, 4});
        land.put(4, new Integer[]{2, 3, 5});
        land.put(5, new Integer[]{2, 4, 8});
        land.put(6, new Integer[]{1, 2, 7, 8});
        land.put(7, new Integer[]{6});
        land.put(8, new Integer[]{2, 5, 6});
        land.put(9, new Integer[]{10});
        land.put(10, new Integer[]{9, 11});
        land.put(11, new Integer[]{10});
        land.put(12, new Integer[]{13});
        land.put(13, new Integer[]{12});
        land.put(14, new Integer[]{15});
        land.put(15, new Integer[]{14});
        land.put(16, new Integer[]{17, 18, 19});
        land.put(17, new Integer[]{16, 19});
        land.put(18, new Integer[]{16, 19, 20, 21});
        land.put(19, new Integer[]{16, 17, 18, 21, 22});
        land.put(20, new Integer[]{18, 21});
        land.put(21, new Integer[]{18, 19, 20, 22});
        land.put(22, new Integer[]{19, 21});

        //inicializar possibilidades de mover exercitos por mar
        naval.put(0, new Integer[]{12, 17});
        naval.put(3, new Integer[]{22});
        naval.put(7, new Integer[]{9});
        naval.put(9, new Integer[]{7});
        naval.put(11, new Integer[]{12});
        naval.put(12, new Integer[]{0, 11});
        naval.put(13, new Integer[]{14});
        naval.put(14, new Integer[]{13});
        naval.put(15, new Integer[]{16});
        naval.put(16, new Integer[]{15});
        naval.put(17, new Integer[]{0});
        naval.put(22, new Integer[]{3});

        //inicializar continentes
        continent.put(0, new Integer[]{0, 1, 2, 3, 4, 5, 6, 7, 8});
        continent.put(1, new Integer[]{9, 10, 11});
        continent.put(2, new Integer[]{12, 13});
        continent.put(3, new Integer[]{14, 15});
        continent.put(4, new Integer[]{16, 17, 18, 19, 20, 21, 22});
    }

    //Army
    public boolean checkMovementEarth(Player p, int start, int finish) {
        if (start != -1) {
            for (int i = 0; i < troop.get(start).size(); i++) {
                if (troop.get(start).get(i).getOwner().equals(p)) {
                    for (Integer get : land.get(start)) {
                        if (get == finish) {
                            return true;
                        }

                    }
                }
            }
        }
        return false;
    }

    public boolean checkMovementWater(Player p, int start, int finish) {
        if (start != -1) {
            for (int i = 0; i < troop.get(start).size(); i++) {
                if (troop.get(start).get(i).getOwner().equals(p)) {
                    for (Integer get : naval.get(start)) {

                        if (get == finish) {
                            return true;
                        }

                    }
                }
            }
        }
        return false;
    }

    public boolean checkArmy(int place) {
        return !troop.get(place).isEmpty();
    }

    public boolean checkArmyPresence(Player p, int place) {
        for (int i = 0; i < troop.get(place).size(); i++) {
            if (troop.get(place).get(i).getOwner().getName().equals(p.getName())) {
                return true;
            }
        }
        return false;
    }

    public void moveArmy(Player p, int start, int finish) {
        for (int i = 0; i < troop.get(start).size(); i++) {
            if (troop.get(start).get(i).getOwner().equals(p)) {
                troop.get(finish).add(troop.get(start).get(i));
                troop.get(start).remove(i);
                return;
            }
        }
    }

    public int checkErase(int place) {
        return troop.get(place).size();
    }

    public boolean checkPlace(Player p, int place) {
        for (int i = 0; i < city.get(place).size(); i++) {
            if (city.get(place).get(i).getOwner().equals(p)) {
                return true;
            }
        }
        return false;
    }

    public void placeArmy(Player p, int place) {

        for (int i = 0; i < city.get(place).size(); i++) {
            if (city.get(place).get(i).getOwner().equals(p)) {
                troop.get(place).add(p.getTroop());
            }
        }

        if (place == 0) {
            troop.get(0).add(p.getTroop());
        }
    }

    public Army eraseArmy(Player p, int place) {
        for (int i = 0; i < troop.get(place).size(); i++) {
            if (troop.get(place).get(i).getOwner().equals(p)) {
                Army a = troop.get(place).get(i);
                troop.get(place).remove(i);
                return a;
            }
        }
        return null;
    }

    public HashMap<Integer, ArrayList<Army>> getTroop() {
        return troop;
    }

    public StringBuilder troopToString(ArrayList<Player> p, int place) {
        StringBuilder str = new StringBuilder();
        str.append("Tropas:\n");

        str.append(" (").append(place).append(")\t\t").append(" ");
        int aux = 0;

        for (int h = 0; h < p.size(); h++) {
            aux = 0;
            for (int x = 0; x < troop.get(place).size(); x++) {
                if (troop.get(place).get(x).owner.equals(p.get(h))) {
                    aux++;
                }
            }
            if (aux != 0) {
                str.append(p.get(h).getName()).append(" (").append(aux).append(") \t");
            }
        }
        str.append("\n");

        return str;
    }

    public ArrayList<Player> getPPlace(ArrayList<Player> p, int place) {
        ArrayList<Player> aux = new ArrayList<>();

        for (int i = 0; i < p.size(); i++) {
            for (int j = 0; j < troop.get(j).size(); j++) {
                if (troop.get(place).get(j).owner.equals(p.get(i))) {
                    if (!aux.contains(p.get(i))) {
                        aux.add(p.get(i));
                    }
                }
            }
        }

        return aux;
    }

    //City's
    public void foundCity(Player p, int place) {
        city.get(place).add(p.getEmpire());

    }

    public StringBuilder cityToString(int place) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < troop.get(place).size(); i++) {
            str.append(i + 1).append(" ").append(troop.get(place).get(i).owner.getName()).append("\n");
        }
        return str;
    }

    //contagem
    public void countPlace(ArrayList<Player> p) {
        int count, biggest;
        Player temp, winner;

        //ciclo de sitios
        for (int i = 0; i <= 22; i++) {
            winner = null;
            biggest = 0;

            //ciclo dos jogadores
            for (int j = 0; j < p.size(); j++) {

                count = 0;
                temp = p.get(j);

                //cada regiao tropas
                if (troop.containsKey(i)) {
                    for (int x = 0; x < troop.get(i).size(); x++) {
                        if (temp.getName().equals(troop.get(i).get(x).getOwner().getName())) {
                            count++;
                        }
                    }
                }

                //cada regiao cidades
                if (city.containsKey(i)) {
                    for (int k = 0; k < city.get(i).size(); k++) {
                        if (temp.getName().equals(troop.get(i).get(k).getOwner().getName())) {
                            count++;
                        }
                    }
                }

                if (count > biggest) {
                    winner = temp;
                    biggest = count;
                } else if (count == biggest) {
                    winner = null;
                }
            }

            if (winner != null) {
                winner.setVictoryPoints(1);

                for (int k = 0; k < continent.size(); k++) {

                    for (int d = 0; d < continent.get(k).length; d++) {
                        Integer place = i;
                        if (continent.get(k)[d].equals(place)) {
                            winner.addEmpireOwned(k);
                            break;
                        }
                    }
                }
            }

        }
    }

    public void countContinentPoints(ArrayList<Player> p) {
        int count, biggest;
        Player temp, winner;

        //ciclo continentes
        for (int i = 0; i < continent.size(); i++) {
            biggest = 0;
            winner = null;

            //ciclo jogadores
            for (int j = 0; j < p.size(); j++) {
                count = 0;
                temp = p.get(j);

                count = temp.getNEmpiresOwned(i);

                if (count > biggest) {
                    winner = temp;
                    biggest = count;
                } else if (count == biggest) {
                    winner = null;
                }
            }
            if (winner != null) {
                winner.setVictoryPoints(1);
            }
        }

    }

    public int countTroops(Player p) {
        int count = 0;
        for (int i = 0; i < 23; i++) {
            for (int x = 0; x < troop.get(i).size(); x++) {
                if (p.equals(troop.get(i).get(x).getOwner())) {
                    count++;
                }
            }
        }
        return count;
    }

    public StringBuilder toString(ArrayList<Player> p) {

        StringBuilder str = new StringBuilder();
        str.append("\nTropas:\n");

        for (int i = 0; i < troop.size(); i++) {
            if (!troop.get(i).isEmpty()) {
                str.append(" (").append(i).append(")\t\t").append(" ");
                int aux = 0;

                for (int h = 0; h < p.size(); h++) {
                    aux = 0;
                    for (int x = 0; x < troop.get(i).size(); x++) {
                        if (troop.get(i).get(x).owner.equals(p.get(h))) {
                            aux++;
                        }
                    }
                    if (aux != 0) {
                        str.append(p.get(h).getName()).append(" (").append(aux).append(") \t");
                    }
                }
                str.append("\n");
            }
        }

        str.append("\nCidades:\n");

        for (int i = 0; i < city.size(); i++) {

            if (!city.get(i).isEmpty()) {
                int aux = 0;

                for (int h = 0; h < p.size(); h++) {
                    aux = 0;
                    for (int x = 0; x < city.get(i).size(); x++) {
                        if (city.get(i).get(x).owner.equals(p.get(h))) {
                            aux++;
                        }
                    }

                    if (aux != 0) {
                        str.append(" (").append(i).append(")\t\t").append(" ");
                        str.append(p.get(h).getName()).append(" (").append(aux).append(") \t");

                    }
                }
                str.append("\n");
            }
        }

        return str;
    }

    public HashMap troopToColor() {
        HashMap<Integer, ArrayList> cores = new HashMap<>();
        for (int i = 0; i < 23; i++) {
            cores.put(i, new ArrayList<Color>());
        }
        for (int i = 0; i < 23; i++) {
            if (!troop.get(i).isEmpty()) {
                for (int j = 0; j < troop.get(i).size(); j++) {
                    cores.get(i).add(troop.get(i).get(j).getOwner().getColor());
                }
            }
        }
        return cores;
    }
}
